home *** CD-ROM | disk | FTP | other *** search
Text File | 1996-07-03 | 4.7 KB | 160 lines | [TEXT/R*ch] |
- (* Real.sml -- 1995-05-24 *)
-
- type real = real
-
- exception Div = Div
- and Overflow = Overflow;
-
- fun ceil r = ~(floor (~r));
- val floor = floor;
- fun trunc r = if r >= 0.0 then floor r else ceil r;
-
- (* The following is rather inefficient, but correct. A faster method
- exists, see src/sml-nj/boot/math.sml, but that does not work on a
- number such as 1000001.4999, which gets rounded to 1000002.0 (but only on
- an x86 computing with extended precision). *)
-
- fun round r =
- let prim_val andb_ : int -> int -> int = 2 "and";
- val rf = floor r
- val df = r - real rf
- in
- if df > 0.5 orelse df = 0.5 andalso andb_ 1 rf = 1 then rf + 1
- else rf
- end
-
- val real = real;
-
- (* The following should be replaced by numerically better conversion
- functions; see
-
- Steele and White : How to print floating-point numbers accurately,
- PLDI'90, pages 112-123, and
-
- Clinger: How to read floating-point numbers accurately, PLDI'90, pages
- 92-101.
-
- D.M. Gay: Correctly rounded binary-decimal and decimal-binary
- conversions, AT&T Bell Labs, Numerical Analysis Manuscript 90-10,
- November 30, 1990 *)
-
- fun fmt spec r =
- let prim_val to_string : string -> real -> string
- = 2 "sml_general_string_of_float";
- fun fracdigs NONE = "%"
- | fracdigs (SOME n) = "%." ^ makestring (if n < 0 then 0 else n)
- open StringCvt
- val cfmtspec =
- case spec of
- SCI arg => fracdigs arg ^ "e"
- | FIX arg => fracdigs arg ^ "f"
- | GEN NONE => "%.12g"
- | GEN arg => fracdigs arg ^ "g"
- in to_string cfmtspec r end
-
- fun toString r = fmt (StringCvt.GEN NONE) r;
-
- fun scan {getc} source =
- let fun decval c = Char.ord c - 48
- fun pow10 0 = 1.0
- | pow10 n =
- if n rem 2 = 0 then
- let val x = pow10 (n quot 2) in x * x end
- else 10.0 * pow10 (n-1)
- fun pointsym src =
- case getc src of
- NONE => (false, src)
- | SOME (c, rest) => if c = #"." then (true, rest)
- else (false, src)
- fun esym src =
- case getc src of
- NONE => (false, src)
- | SOME (c, rest) =>
- if c = #"e" orelse c = #"E" then
- (true, rest)
- else (false, src)
- fun scandigs first next final source =
- let fun digs state src =
- case getc src of
- NONE => (SOME (final state), src)
- | SOME(c, rest) =>
- if Char.isDigit c then
- digs (next(state, decval c)) rest
- else
- (SOME (final state), src)
- in
- case getc source of
- NONE => (NONE, source)
- | SOME(c, rest) =>
- if Char.isDigit c then digs (first (decval c)) rest
- else (NONE, source)
- end
-
- fun ident x = x
- val getint =
- scandigs real (fn (res, cval) => 10.0 * res + real cval) ident
- val getfrac =
- scandigs (fn cval => (1, real cval))
- (fn ((decs, frac), cval) => (decs+1, 10.0*frac+real cval))
- (fn (decs, frac) => frac / pow10 decs)
- val getexp = scandigs ident (fn (res, cval) => 10 * res + cval) ident
-
- fun sign src =
- case getc src of
- SOME(#"+", rest) => (true, rest)
- | SOME(#"-", rest) => (false, rest)
- | SOME(#"~", rest) => (false, rest)
- | _ => (true, src )
-
- val src = StringCvt.skipWS {getc=getc} source
- val (manpos, src) = sign src
- val (intg, src) = getint src
- val (decpt, src) = pointsym src
- val (frac, src) = getfrac src
- val (esym, src) = esym src
- val (exppos, src) = sign src
- val (expv, rest) = getexp src
-
- fun mkres manval =
- let val res = if manpos then manval else ~manval
- in
- case (esym, expv) of
- (false, NONE ) => SOME(res, rest)
- | (true, SOME exp) =>
- if exppos then SOME(res * pow10 exp, rest)
- else SOME(res / pow10 exp, rest)
- | _ => NONE
- end
- in
- case (intg, decpt, frac) of
- (NONE, true, SOME fval) => mkres fval
- | (SOME ival, false, SOME _ ) => NONE
- | (SOME ival, _ , NONE ) => mkres ival
- | (SOME ival, _ , SOME fval) => mkres (ival+fval)
- | _ => NONE
- end;
-
- val fromString = StringCvt.scanString scan;
-
- val ~ : real -> real = ~;
- val op + : real * real -> real = op +;
- val op - : real * real -> real = op -;
- val op * : real * real -> real = op *;
- val op / : real * real -> real = op /;
- val op > : real * real -> bool = op >;
- val op >= : real * real -> bool = op >=;
- val op < : real * real -> bool = op <;
- val op <= : real * real -> bool = op <=;
- val abs : real -> real = abs;
- fun sign i = if i > 0.0 then 1 else if i < 0.0 then ~1 else 0;
- fun compare (x, y: real) =
- if x<y then LESS else if x>y then GREATER else EQUAL;
-
- fun sameSign (i, j) = sign i = sign j;
-
- fun min (x, y) = if x < y then x else y : real;
- fun max (x, y) = if x < y then y else x : real;
-
- fun toDefault i = i;
- fun fromDefault i = i;
-